Setting up a Machine Client to use IdentityServer and Access an API

If you haven’t already, follow the installation steps here first.

Table of Contents

  1. Dependencies
  2. Configuring the IdentityServer
  3. Connecting the Client
  4. Calling the API

Dependencies

  1. .Net 7 SDK

Configuring the IdentityServer

In order to utilize this client, we need to add it to the list of Clients in the IdentityServer project. In the Config.cs file of the IdentityServer add to the Clients property:

public static IEnumerable<Client> Clients =>
  new List<Client>
  {
      new Client
      {
          ClientId = "client",

          // no interactive user, use the clientid/secret for authentication
          AllowedGrantTypes = GrantTypes.ClientCredentials,

          // secret for authentication
          ClientSecrets =
          {
              new Secret("secret".Sha256())
          },

          // scopes that client has access to
          AllowedScopes = { "api1" }
      }
  };

Connecting the Client

If you already have a .NET solution and are connecting the client to the IdentityServer, skip this step. Otherwise, if you are starting with a fresh .NET solution, create a new .NET project in the src directory and add it to the solution:

dotnet new console -n Client
cd ..
dotnet sln add ./src/Client/Client.csproj

Add the IdentityModel nuget package to the project:

dotnet add ./src/Client/Client.csproj package IdentityModel

Add the following in the Program.cs file, to discover endpoints from metadata:

using System.Text.Json;
using IdentityModel.Client;

// discover endpoints from metadata
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("URI of IdentityServer");
if (disco.IsError)
{
  Console.WriteLine(disco.Error);
  return;
}

Now we can use the information from the discovery document to request a token:

// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
  Address = disco.TokenEndpoint,

  ClientId = "client",
  ClientSecret = "secret",
  Scope = "api1"
});

if (tokenResponse.IsError)
{
  Console.WriteLine(tokenResponse.Error);
  return;
}

Console.WriteLine(tokenResponse.AccessToken);

Calling the API

With a token from the IdentityServer, configured with the proper scope, we can make a call to the API:

// call api
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);

var response = await apiClient.GetAsync("URI of API and service to request");
if (!response.IsSuccessStatusCode)
{
  Console.WriteLine(response.StatusCode);
}
else
{
  // Utilize response from the API
}